/**
 * Copyright (C), 2021-2023, 四信物联网有限公司
 * FileName: BeiDouCodec
 * Author:   Chapin
 * Date:     2023/10/23 15:36
 * Description: 北斗3编解码
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.fourfaith.iot.beidou.decodec;

import cn.hutool.core.util.HexUtil;
import com.fourfaith.iot.beidou.message.BeiDouProcotolMessage;
import com.fourfaith.iot.beidou.message.Message;
import com.fourfaith.iot.beidou.utils.ObjectOperate;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 〈北斗3编解码〉
 * @author Chapin
 * @create 2023/10/23
 * @since 1.0.0
 */
@Slf4j
public class BeiDouCodec extends MessageToMessageCodec<ByteBuf,Message> {

    /**
     * 日志记录编码后的数据
     *
     * @param bytes 编码后的字节数组
     */
    private void logEncodedData(byte[] bytes) {
        if (log.isDebugEnabled()) {
            log.debug("写数据：{}", HexUtil.encodeHexStr(bytes));
        }
    }

    /**
     * 编码消息为ByteBuf对象，准备发送到通道
     *
     * @param ctx 通道处理上下文
     * @param msg 待编码的消息对象
     * @param outList 存放编码后的数据的列表
     * @throws Exception 编码过程中可能抛出的异常
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        try {
            // 分配一个新的ByteBuf对象，用于存储编码后的字节数据
            ByteBuf out = ctx.alloc().buffer();
            // 将消息对象编码为字节数组
            byte[] bytes = BeiDouEncoder.encodeToByte(msg);
            // 将字节数组写入ByteBuf
            out.writeBytes(bytes);
            // 记录编码后的数据
            logEncodedData(bytes);
            // 将编码后的ByteBuf对象添加到输出列表中，准备发送
            outList.add(out);
        } catch (Exception e) {
            // 记录编码过程中发生的错误
            log.error("编码失败", e);
            // 将异常传递给下一个处理器
            ctx.fireExceptionCaught(e);
        }
    }
    /**
     * 解码函数，用于处理接收到的消息
     *
     * @param ctx 通道处理上下文，提供了与通道相关的上下文信息和操作方法
     * @param msg 接收到的消息，封装在ByteBuf中
     * @param out 解码后的消息输出列表
     * @throws Exception 如果解码过程中发生错误，则抛出异常
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        try {
            // 获取可读字节数
            int readableBytes = msg.readableBytes();
            // 如果有可读字节
            if (readableBytes > 0) {
                // 创建一个数组来存储可读字节
                byte[] bytes = new byte[readableBytes];
                // 将可读字节读取到数组中
                msg.readBytes(bytes);
                // 将字节数组转换为字符串，使用US_ASCII字符集解码
                String decodeStr = new String(bytes, StandardCharsets.US_ASCII);
                // 使用解码后的字符串调用解码器
                Object object = BeiDouEncoder.decode(decodeStr);
                // 如果解码成功，将结果添加到输出列表中
                if (object != null) {
                    out.add(object);
                }
            }
        } catch (Exception e) {
            // 记录解码失败的错误日志
            log.error("解码失败", e);
            // 将异常传递给下一个处理器
            ctx.fireExceptionCaught(e);
        }
    }
}